#include <algorithm/analytical_model/Constants.h>
#include <algorithm/analytical_model/algorithm/PeakFluxParam.h>
#include <algorithm/shared/utils/Vec3.h>
#include <utils/Math.h>

namespace solar
{
    constexpr auto airAttenuationEfficiency(double distance) -> double
    {
        return (distance <= 1000)
                   ? (0.99321 - 0.0001176 * distance + 1.97 * 1e-8 * distance * distance)
                   : const_expr::exp(-0.0001106 * distance);
    }
} // namespace solar

using namespace solar;

auto solar::peakFluxParam(const ModelType& model_type, const Vec3& focus_center,
                          const Vec3& helio_pos, const Vec3& helio_normal, double helio_area,
                          double DNI, double reflectivity) -> double
{
    const auto distance_vec = focus_center - helio_pos;
    const auto distance = distance_vec.length();
    const auto air_attenuation_efficiency = airAttenuationEfficiency(distance);
    const auto cos_w = solar::dot(distance_vec.get_unit_vector(), helio_normal);
    switch (model_type)
    {
    case ModelType::kSimplified:
    {
        return DNI * helio_area * cos_w * reflectivity * air_attenuation_efficiency;
    }
    case ModelType::kConvolution:
        return DNI * cos_w * reflectivity * air_attenuation_efficiency;
    }
}
